package com.why.cachecloud.client.redis.cachecloud.client.lettuce.util.util;

import io.lettuce.core.GeoCoordinates;

import java.util.*;

/**
 * @Description
 * @Author why
 * @Version 1.0.0
 * @Since 1.0
 * @Date 2022/8/30
 */
public interface RedisUtil<T> {

    /**
     * set 命令
     *
     * @param key
     * @param value
     */
    void set(String key, T value);

    /**
     * 将值 value 关联到 key ，并将 key 的过期时间设为单位{seconds} 过期时间 单位秒
     *
     * @param key
     * @param value
     * @param seconds
     */
    void set(String key, T value, long seconds);


    /**
     * get command
     *
     * @param key
     * @return
     */
    T get(String key);

    /**
     * del key 删除
     *
     * @param key
     */
    void del(String key);

    /**
     * del keys
     *
     * @param keys
     */
    void del(String... keys);

    /**
     * 返回value的长度
     *
     * @param key
     * @return
     */
    long strLen(String key);

    /**
     * incr command
     *
     * @param key
     * @return
     */
    long incr(String key);

    /**
     * decr command
     *
     * @param key
     * @return
     */
    long decr(String key);

    /**
     * incrBy command  同incr，对key的值加increment
     *
     * @param key
     * @param increment
     * @return
     */
    long incrBy(String key, long increment);

    /**
     * 命令在指定的 key 不存在时，为 key 设置指定的值
     *
     * @param key
     * @param value
     * @return
     */
    boolean setNx(String key, T value);

    /**
     * 获取原有value,并设置新的value
     *
     * @param key
     * @param value
     * @return
     */
    T getSet(String key, T value);

    /**
     * 设置key过期时间 单位秒
     *
     * @param key
     * @param seconds
     */
    Boolean expire(String key, long seconds);

    /**
     * 指定时间过期key
     *
     * @param key
     * @param date
     * @return
     */
    Boolean expireAt(String key, Date date);

    // string end

    /**
     * 添加地理位置的坐标
     *
     * @param key
     * @param longitude
     * @param latitude
     * @param member
     */
    void geoAdd(String key, double longitude, double latitude, T member);

    /**
     * geoOps : 获取指定位置的坐标
     */
    List<GeoCoordinates> geoPos(String key, T... members);

    /**
     * 获取两个位置之间的距离 目前返回km
     *
     * @param key
     * @param source
     * @param dest
     * @return
     */
    Double geoDist(String key, T source, T dest);

    /**
     * 获取库中指定位置指定范围内的城市
     *
     * @param key
     * @param longitude
     * @param latitude
     * @param radius
     * @return
     */
    Set<T> geoRadius(String key, double longitude, double latitude, double radius);

    /**
     * 获取库中指定城市指定范围内的城市
     *
     * @param key
     * @param radius
     * @param member
     * @return
     */
    Set<T> geoRadiusByMember(String key, double radius, T member);


    /**
     * 将一个或多个值 value 插入到列表 key 的表尾(最右边)
     *
     * @param key    list key
     * @param values 字符串values
     */
    void rPush(String key, T... values);

    /**
     * 将一个或多个值 value 插入到列表 key 的表头(最左边)
     *
     * @param key
     * @param values
     */
    void lPush(String key, T... values);

    /**
     * 将值 value 插入到列表 key 当中，位于值 pivot 之前或之后
     *
     * @param key
     * @param before      在之前插入 为true 否则为false
     * @param pivot
     * @param insertValue
     */
    void lInsert(String key, boolean before, T pivot, T insertValue);

    /**
     * 返回列表 key 中指定区间 [start, stop] 内的元素
     *
     * @param key
     * @param start
     * @param end
     * @return
     */
    List<T> lRange(String key, int start, int end);

    /**
     * 返回列表 key 中，下标为 index 的元素
     *
     * @param key
     * @param index
     * @return
     */
    T lIndex(String key, long index);

    /**
     * 返回列表 key 的长度
     *
     * @param key
     * @return
     */
    Long lLen(String key);

    /**
     * 移除并返回列表 key 的头元素
     *
     * @param key
     * @return
     */
    T lPop(String key);

    /**
     * 移除并返回列表 key 的尾元素
     *
     * @param key
     * @return
     */
    T rPop(String key);

    /**
     * 根据参数 count 的值，移除列表中与参数 value 相等的元素
     *
     * @param key
     * @param count
     * @param value
     */
    void lRem(String key, long count, T value);

    /**
     * 对一个列表进行修剪(trim)，保留区间 [start, end] 内的元素
     *
     * @param key
     * @param start
     * @param end
     */
    void lTrim(String key, long start, long end);

    /**
     * 将列表 key 下标为 index 的元素的值设置为 value
     *
     * @param key
     * @param index
     * @param value
     */
    void lSet(String key, long index, T value);

    /**
     * 弹出key对应的第一个非空列表的头元素
     *
     * @param key
     * @param timeout
     * @throws InterruptedException
     */
    T blPop(String key, long timeout);

    /**
     * 弹出key对应的最后一个非空列表的头元素
     *
     * @param key
     * @param timeout
     * @throws InterruptedException
     */
    T brPop(String key, long timeout);

    /**
     * 将哈希表 key 中的域 field 的值设为 value
     *
     * @param key
     * @param field
     * @param value
     */
    void hSet(String key, String field, T value);

    /**
     * 返回哈希表 key 中给定域 field 的值
     *
     * @param key
     * @param field
     * @return
     */
    T hGet(String key, String field);

    /**
     * 删除哈希表 key 中的一个或多个指定域，不存在的域将被忽略
     *
     * @param key
     * @param fields
     */
    void hDel(String key, String... fields);

    /**
     * 返回哈希表 key 中域的数量
     *
     * @param key
     * @return
     */
    long hLen(String key);

    /**
     * 返回哈希表 key 中，所有的域 field 和值 value
     *
     * @param key
     * @return
     */
    Map<String, T> hGetAll(String key);

    /**
     * 返回哈希表 key 中，一个或多个给定域的值
     *
     * @param key
     * @param fields
     * @return
     */
    Map<String, T> hmGet(String key, String... fields);

    /**
     * 同时将多个 field-value (域-值)对设置到哈希表 key 中
     *
     * @param key
     * @param kvs
     */
    void hmSet(String key, Map<String, T> kvs);

    /**
     * 查看哈希表 key 中，给定域 field 是否存在
     *
     * @param key
     * @param field
     * @return
     */
    boolean hExists(String key, String field);

    /**
     * 返回哈希表 key 中的所有域 field
     *
     * @param key
     * @return
     */
    List<String> hKeys(String key);

    /**
     * 返回哈希表 key 中所有域的值 value
     *
     * @param key
     * @return
     */
    List<T> hVals(String key);

    /**
     * 将哈希表 key 中的域 field 的值设置为 value ，当且仅当域 field 不存在能设置成功
     *
     * @param key
     * @param field
     * @param value
     * @return
     */
    Boolean hSetNx(String key, String field, T value);

    /**
     * 为哈希表 key 中的域 field 的值加上整数增量 increment
     *
     * @param key
     * @param field
     * @param increment
     */
    void hIncrBy(String key, String field, long increment);

    /**
     * 为哈希表 key 中的域 field 的值加上整数增量 increment(浮点型)
     *
     * @param key
     * @param field
     * @param increment
     */
    void hIncrByFloat(String key, String field, double increment);

    /**
     * 返回field的string长度
     *
     * @param key
     * @param field
     * @return
     */
    long hStrLen(String key, String field);

    /**
     * 将一个或多个 member 元素加入到集合 key 当中，已经存在于集合的 member 元素将被忽略
     *
     * @param key
     * @param elements
     */
    void sAdd(String key, T... elements);

    /**
     * 移除集合 key 中的一个或多个 member 元素，不存在的 member 元素会被忽略
     *
     * @param key
     * @param elements
     */
    void sRem(String key, T... elements);

    /**
     * 返回集合 key 中元素的数量
     *
     * @param key
     * @return
     */
    long sCard(String key);

    /**
     * 判断集合 key 是否包含 member 元素
     *
     * @param key
     * @param element
     * @return
     */
    boolean sIsMember(String key, T element);

    /**
     * 移除并返回集合中的一个随机元素
     *
     * @param key
     * @return
     */
    T sPop(String key);

    /**
     * 返回集合 key 中的所有成员
     *
     * @param key
     * @return
     */
    Set<T> sMembers(String key);

    /**
     * 返回一个集合的全部成员，该集合是所有给定集合的交集
     *
     * @param key1
     * @param key2
     * @return
     */
    Set<T> sInter(String key1, String key2);

    /**
     * 返回一个集合的全部成员，该集合是所有给定集合的并集
     *
     * @param key1
     * @param key2
     * @return
     */
    Set<T> sUnion(String key1, String key2);

    /**
     * 返回一个集合的全部成员，该集合是所有给定集合之间的差集
     *
     * @param key1
     * @param key2
     * @return
     */
    Set<T> sDiff(String key1, String key2);

    // set end

    /**
     * 将一个或多个 member 元素及其 score 值加入到有序集 key 当中
     *
     * @param key
     * @param elements
     */
    void zAdd(String key, Map<T, Double> elements);


    /**
     * 将一个 member 元素及其 score 值加入到有序集 key 当中
     *
     * @param key
     */
    void zAdd(String key, T member, Double socre);

    /**
     * 返回集合 key 中元素的数量
     *
     * @param key
     * @return
     */
    long zCard(String key);

    /**
     * 返回有序集 key 中， score 值在 min 和 max 之间(默认包括 score 值等于 min 或 max )的成员的数量
     *
     * @param key
     * @param minScore
     * @param maxScore
     * @return
     */
    Long zCount(String key, double minScore, double maxScore);

    /**
     * 为有序集 key 的成员 member 的 score 值加上增量 increment
     *
     * @param key
     * @param member
     * @param increment
     * @return
     */
    Double zIncrBy(String key, T member, double increment);

    /**
     * 计算给定的一个或多个有序集的并集
     *
     * @param destKey
     * @param keys
     */
    void zInterStore(String destKey, String... keys);

    /**
     * 并集
     *
     * @param destKey
     * @param keys
     */
    void zUnionStore(String destKey, String... keys);

    /**
     * 返回有序集 key 中，指定下标区间 [start, stop] 内的元素。其中成员的位置按 score 值递增(从小到大)来排序
     * 按照索引位置返回信息
     *
     * @param key
     * @param start
     * @param end
     * @return
     */
    List<T> zRange(String key, long start, long end);

    /**
     * 返回有序集 key 中，指定下标区间 [start, stop] 内的元素。其中成员的位置按 score 值递增(从大到小)来排序
     * 按照索引位置返回信息
     *
     * @param key
     * @param start
     * @param end
     * @return
     */
    List<T> zRevRange(String key, long start, long end);

    /**
     * 返回有序集 key 中，所有 score 值介于 [min, max] 之间的成员有序集成员按 score 值递增(从小到大)次序排列
     * 按照score
     *
     * @param key
     * @param minScore
     * @param maxScore
     * @return
     */
    List<T> zRangeByScore(String key, double minScore, double maxScore);

    /**
     * 返回有序集 key 中，所有 score 值介于 [min, max] 之间的成员有序集成员按 score 值递增(从大到小)次序排列
     * 按照score
     *
     * @param key
     * @param minScore
     * @param maxScore
     * @return
     */
    List<T> zRevRangeByScore(String key, double minScore, double maxScore);

    /**
     * 返回有序集 key 中元素的排名 rank。其中有序集成员按 score 值递增(从小到大)顺序排列
     *
     * @param key
     * @param member
     * @return
     */
    long zRank(String key, T member);

    /**
     * 返回有序集 key 中元素的排名 rank。其中有序集成员按 score 值递增(从大到小)顺序排列
     *
     * @param key
     * @param member
     * @return
     */
    long zRevRank(String key, T member);

    /**
     * 移除有序集 key 中的一个或多个成员，不存在的成员将被忽略
     *
     * @param key
     * @param members
     * @return
     */
    Long zRem(String key, T... members);

    /**
     * 移除有序集 key 中，指定下标排名(rank)区间 [start, stop] 内的所有成员
     *
     * @param key
     * @param start
     * @param end
     * @return
     */
    long zRemRangeByRank(String key, long start, long end);

    /**
     * 移除有序集 key 中，所有 score 值介于 [minScore, maxScore] 之间
     *
     * @param key
     * @param minScore
     * @param maxScore
     * @return
     */
    long zRemRangeByScore(String key, double minScore, double maxScore);

    /**
     * 返回有序集 key 中，成员 member 的 score 值
     *
     * @param key
     * @param member
     * @return
     */
    Double zScore(String key, T member);

    // zset end


    /**
     * 命令将所有元素参数添加到 HyperLogLog 数据结构
     *
     * @param key
     * @param elements
     */
    void pfAdd(String key, T... elements);

    /**
     * 命令返回给定 HyperLogLog 的基数估算值
     *
     * @param key
     * @return
     */
    long pfCount(String key);

    /**
     * 命令将多个 HyperLogLog 合并为一个 HyperLogLog ，合并后的 HyperLogLog 的基数估算值是通过对所有 给定 HyperLogLog 进行并集计算得出
     *
     * @param destKey
     * @param sourceKeys
     */
    void pfMerge(String destKey, String... sourceKeys);
}
